package com.moon.admin.flowable.controller;

import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;

import javax.activation.MimetypesFileTypeMap;
import javax.servlet.http.HttpServletResponse;

import org.flowable.engine.ProcessEngine;
import org.flowable.engine.repository.DeploymentQuery;
import org.flowable.ui.modeler.domain.Model;
import org.flowable.ui.modeler.serviceapi.ModelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.moon.admin.flowable.entity.ActCnDeploymentEntity;
import com.moon.admin.flowable.entity.ActCnModelEntity;
import com.moon.admin.flowable.entity.ActGeByteArrayEntity;
import com.moon.admin.flowable.service.FlowableModelService;
import com.moon.admin.framework.secure.annotation.FormRepeat;
import com.moon.admin.framework.secure.annotation.PreAuth;
import com.moon.admin.framework.springmvc.domain.R;
import com.moon.admin.framework.syslog.annotation.SysLog;
import com.moon.admin.framework.util.FileUtils;
import com.moon.admin.framework.util.MoonException;
import com.moon.admin.framework.util.ToolUtils;

import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

/**
 * 流程模板管理控制器
 * @author ninglong
 * @date 2020年1月13日
 */
@RestController
@RequestMapping("/flowable/modeler")
@Slf4j
public class FlowableModelerController{
	
	@Autowired
	private FlowableModelService flowableModelService;
	@Autowired
	private ModelService modelService;
	@Autowired
	private ProcessEngine processEngine;
	
	/**
	 * 预览流程图
	 */
	@GetMapping("/diagram")
	public R<String> diagram(String modelKey,String processInstanceId){
		InputStream in = flowableModelService.getModelerDiagramByModelKey(modelKey,processInstanceId);
		if(in==null) {
			return R.fail("预览流程图失败");
		}
		try {
			String image = FileUtils.getBase64FromInputStream(in);
			return R.success("data:image/png;base64,"+image);
		} catch (Exception e) {
			log.error(e.getMessage(),e);
		}
		return  R.fail("预览流程图失败");
	}
	
	/**
	 * 查询待部署流程
	 */
	@PreAuth("flowable_modeler_view")
	@PostMapping("undeployList")
	public R<IPage<ActCnModelEntity>> list(@RequestBody ActCnModelEntity model){
		return R.success(flowableModelService.selectModelUndeployList(model));
	}
	
	/**
	 * 查询已部署流程
	 */
	@PreAuth({"flowable_modeler_view"})
	@PostMapping("deployList")
	public R<IPage<ActCnDeploymentEntity>> list(@RequestBody ActCnDeploymentEntity deployment){
		return R.success(flowableModelService.selectModelDeployList(deployment));
	}
	
	@SysLog(mod = "流程模型管理", fun = "部署流程")
	@PreAuth("flowable_modeler_deploy")
	@FormRepeat
	@GetMapping("/deployById")
	public R<Boolean> deployById(String id, String flowModelTypeId) {
		flowableModelService.deployModeler(id, null, flowModelTypeId);
		return R.success();
	}
	
	@SysLog(mod = "流程模型管理", fun = "部署流程")
	@PreAuth("flowable_modeler_deploy")
	@FormRepeat
	@GetMapping("/deployByKey")
	public R<Boolean> deployByKey(String modelKey, String flowModelTypeId) {
		flowableModelService.deployModeler(null, modelKey, flowModelTypeId);
		return R.success();
	}
	
	@SysLog(mod = "流程模型管理", fun = "撤销部署")
	@PreAuth("flowable_modeler_undeploy")
	@FormRepeat
	@GetMapping("/undeploy")
	public R<Boolean> undeploy(String ids) {
		List<String> idList = ToolUtils.toStrList(ids);
		if(ToolUtils.isEmpty(idList)){
			return R.fail("请传入modelId");
		}
		flowableModelService.removeDeployment(idList);
		return R.success();
	}
	
	@SysLog(mod = "流程模型管理", fun = "删除未部署的模型")
	@GetMapping("deleteModelById")
	@PreAuth("flowable_modeler_delete")
	@FormRepeat
	public R<Boolean> deleteModelById(String id) {
		Model model;
		try {
			model = modelService.getModel(id);
		} catch (Exception e) {
			return R.fail("失败，没有查找到ID为【" + id + "】的流程模型");
		}
		DeploymentQuery deploymentQuery = processEngine.getRepositoryService().createDeploymentQuery();
		deploymentQuery.deploymentKey(model.getKey());
		long total = deploymentQuery.count();
		if(total>0) {
			return R.fail("失败，已经部署的流程模型不能删除");
		}
		modelService.deleteModel(id);
		return R.success();
	}
	
	@ApiOperation(value = "下载流程模型xml文件", notes = "传入流程部署id")
	@GetMapping("/getFlowBpmnXmlByDeploymentId")
	public void down(String deploymentId,
					 HttpServletResponse response) throws Exception {
		ActGeByteArrayEntity flowByteArray = flowableModelService.getFlowBpmnXmlByDeploymentId(deploymentId);
		if(flowByteArray==null){
			throw new MoonException("获取流程模型失败");
		}
		String type = new MimetypesFileTypeMap().getContentType(flowByteArray.getName());
		response.setHeader("Content-type", type);
		response.setCharacterEncoding("UTF-8");
		response.setHeader("Content-Disposition", String.format("attachment;filename="+flowByteArray.getName(), System.currentTimeMillis()));
		response.getOutputStream().write(flowByteArray.getBytes().getBytes(StandardCharsets.UTF_8));
		response.flushBuffer();
	}
}